package com.pan.kang.builder;


import cn.hutool.core.util.StrUtil;
import com.pan.kang.constant.FieldTypeEnum;
import com.pan.kang.constant.MockTypeEnum;
import com.pan.kang.model.JavaCodeGenerate;
import com.pan.kang.model.TableSchema;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
public class JavaCodeBuilder {

    @Autowired
    private Configuration configuration;

    public String buildJavaEntityCode(TableSchema tableSchema, String templateFileName) throws TemplateException, IOException {
        // 传递参数
        JavaCodeGenerate javaCodeGenerate = new JavaCodeGenerate();
        String tableName = tableSchema.getTableName();
        String tableComment = tableSchema.getTableComment();
        String upperCamelTableName = StringUtils.capitalize(StrUtil.toCamelCase(tableName));
        javaCodeGenerate.setTableName(tableName);
        // 类名为大写的表名
        javaCodeGenerate.setClassName(upperCamelTableName);
        // 类注释为表注释 > 表名
        javaCodeGenerate.setClassComment(Optional.ofNullable(tableComment).orElse(upperCamelTableName));
        // 依次填充每一列
        List<JavaCodeGenerate.Field> fieldList = new ArrayList<>();
        for (TableSchema.Field field : tableSchema.getFieldList()) {
            JavaCodeGenerate.Field javaField = new JavaCodeGenerate.Field();
            javaField.setComment(field.getComment());
            FieldTypeEnum fieldTypeEnum =
                    Optional.ofNullable(FieldTypeEnum.getFieldTypeByValue(field.getFieldType())).orElse(FieldTypeEnum.TEXT);
            javaField.setJavaType(fieldTypeEnum.getJavaType());
            javaField.setFieldName(StrUtil.toCamelCase(field.getFieldName()));
            javaField.setTableFieldName(field.getFieldName());
            fieldList.add(javaField);
        }
        javaCodeGenerate.setFieldList(fieldList);
        StringWriter stringWriter = new StringWriter();
        Template template = configuration.getTemplate(templateFileName);
        template.process(javaCodeGenerate, stringWriter);
        return stringWriter.toString();
    }

    public String buildJavaObjectCode(TableSchema tableSchema, List<Map<String, Object>> dataList)
            throws IOException, TemplateException {
        // 传递参数
        JavaCodeGenerate codeGenerate = new JavaCodeGenerate();
        String tableName = tableSchema.getTableName();
        String camelTableName = StrUtil.toCamelCase(tableName);
        // 类名为大写的表名
        codeGenerate.setClassName(StringUtils.capitalize(camelTableName));
        // 变量名为表名
        codeGenerate.setObjectName(camelTableName);
        // 默认填充第一条数据
        Map<String, Object> map = dataList.get(0);
        List<JavaCodeGenerate.Field> codeFieldList = new ArrayList<>();
        List<TableSchema.Field> fieldList = tableSchema.getFieldList();
        // 过滤掉不模拟的字段
        fieldList = fieldList.stream()
                .filter(field -> {
                    MockTypeEnum mockTypeEnum = Optional.ofNullable(MockTypeEnum.getMockTypeByValue(field.getMockType()))
                            .orElse(MockTypeEnum.NONE);
                    return !MockTypeEnum.NONE.equals(mockTypeEnum);
                })
                .collect(Collectors.toList());
        for (TableSchema.Field field : fieldList) {
            JavaCodeGenerate.Field codeField = new JavaCodeGenerate.Field();
            // 驼峰字段名
            String fieldName = field.getFieldName();
            codeField.setSetMethod(StrUtil.toCamelCase("set_" + fieldName));
            codeField.setValue(getValueStr(field, map.get(fieldName)));
            codeFieldList.add(codeField);
        }
        codeGenerate.setFieldList(codeFieldList);
        StringWriter stringWriter = new StringWriter();
        Template template = configuration.getTemplate("java_object.ftl");
        template.process(codeGenerate, stringWriter);
        return stringWriter.toString();
    }

    private static String getValueStr(TableSchema.Field field, Object value) {
        if (field == null || value == null) {
            return "''";
        }
        return String.valueOf(value);
    }
}
